package ltd.nullpointer.frontend.web.controller.api;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.boot2.core.HlAssert;
import com.boot2.core.dao.i.SchedulerTaskDao;
import com.boot2.core.scheduler.ScheduleManager;
import com.boot2.core.utils.CronExpressionUtil;
import com.boot2.core.utils.DateUtil;
import com.boot2.core.utils.StringUtils;
import com.boot2.core.vo.Response;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.apachecommons.CommonsLog;
import ltd.nullpointer.frontend.constant.DeviceConstant;
import ltd.nullpointer.frontend.dao.SchedulerTaskToSendTCPMessageDao;
import ltd.nullpointer.frontend.model.entity.SchedulerTaskToSendTCPMessage;
import ltd.nullpointer.frontend.model.entity.down.GetSensorRainData;
import ltd.nullpointer.frontend.schedule.SchedulerTaskConstant;
import ltd.nullpointer.frontend.schedule.SchedulerTaskSensorDataService;
import ltd.nullpointer.frontend.web.controller.ApiBaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

/**
 * @author zhangweilin
 * @date 2019/5/7 14:38
 * @Description: 设备
 */
@Api(tags = "定时读取指定日期雨量数据,命令字 1BH")
@RestController
@RequestMapping("/user/device/getSensorRainData/scheduler")
@CommonsLog
public class GetSensorRainDataController extends ApiBaseController {

    private final String className = GetSensorRainData.class.getName();
    @Autowired
    SchedulerTaskSensorDataService schedulerTaskSensorDataService;
    @Autowired
    SchedulerTaskDao schedulerTaskDao;
    @Autowired
    ScheduleManager scheduleManager;
    @Autowired
    SchedulerTaskToSendTCPMessageDao schedulerTaskToSendTCPMessageDao;

    /**
     * 添加设备一次性倒计时定时任务,多少秒后执行
     *
     * @param sensorNo
     * @param sec
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备一次性倒计时定时任务,多少秒后执行")
    @PostMapping("/oneTime/addBySec/{sec}")
    public Response<String> addBySec(String sensorNo, @PathVariable int sec,Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        Date date = DateUtil.addSec(sec);
        String oneTimeExpression = CronExpressionUtil.getOneTimeExpression(date, date);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, oneTimeExpression);
        return success(sec + "秒后将自动执行");
    }

    private void addSchedule(String sensorNo, Date time1, Date time2, String remark, Boolean isDeleteOneTime, String oneTimeExpression) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(SchedulerTaskConstant.beanClassName, className);
        //DeviceConstant.stationNoSensorNoListMap
        if (StringUtils.isEmpty(sensorNo)) {
            DeviceConstant.stationNoSensorNoListMap.forEach((k, v)->{
                for (String sensorNoTmp : v) {
                    addScheduleBySensorNo(sensorNoTmp, time1, time2, remark, isDeleteOneTime, oneTimeExpression, jsonObject);
                }
            });
        }else{
            String[] sensorNoArr = sensorNo.split("[,，]");
            for (String sensorNo1 : sensorNoArr) {
                addScheduleBySensorNo(sensorNo1, time1, time2, remark, isDeleteOneTime, oneTimeExpression, jsonObject);
            }
        }
        addScheduleBySensorNo(sensorNo, time1, time2, remark, isDeleteOneTime, oneTimeExpression, jsonObject);
    }

    private void addScheduleBySensorNo(String sensorNo, Date time1, Date time2, String remark, Boolean isDeleteOneTime, String oneTimeExpression, JSONObject jsonObject) {
        jsonObject.put(SchedulerTaskConstant.beanJsonValue, JSONObject.toJSONString(new GetSensorRainData(true, sensorNo, time1,time2), SerializerFeature.WriteDateUseDateFormat));
        schedulerTaskSensorDataService.addAndSchedule(sensorNo, jsonObject.toJSONString(), remark, oneTimeExpression, isDeleteOneTime);
    }


    /**
     * 添加设备一次性定时任务,在指定的时分秒执行
     *
     * @param sensorNo
     * @param hour
     * @param min
     * @param sec
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备一次性倒计时定时任务,在指定的时分秒执行")
    @PostMapping("/oneTime/addByTime/{hour}/{min}/{sec}")
    public Response<String> addByTime(String sensorNo, @PathVariable int hour, @PathVariable int min, @PathVariable int sec,Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        Date time = DateUtil.getTime(hour, min, sec);
        String oneTimeExpression = CronExpressionUtil.getOneTimeExpression(time, time);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, oneTimeExpression);
        return success("将于【" + DateUtil.formatDate(time, DateUtil.PATTERN_HH_mm_ss) + "】自动执行");
    }

    /**
     * 添加设备一次性倒计时定时任务,在指定的时分秒执行,time 只接受 HH:mm:ss 格式
     *
     * @param sensorNo
     * @param time        只接受 HH:mm:ss 格式
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备一次性倒计时定时任务,在指定的时分秒执行,time 只接受 HH:mm:ss 格式")
    @PostMapping("/oneTime/addByTime/{time}")
    public Response<String> addByTime(String sensorNo, @PathVariable String time,Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        String oneTimeExpression = CronExpressionUtil.getOneTimeExpression(time, time);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, oneTimeExpression);
        return success("将于【" + time + "】自动执行");

    }


    /**
     * 添加设备每天重复定时任务
     *
     * @param sensorNo
     * @param hour
     * @param min
     * @param sec
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备每天重复定时任务 ")
    @PostMapping("/addEveryDayByTime/{hour}/{min}/{sec}")
    public Response<String> addEveryDayByTime(String sensorNo, @PathVariable int hour, @PathVariable int min, @PathVariable int sec,Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        Date time = DateUtil.getTime(hour, min, sec);
        String expression = CronExpressionUtil.getExpression(time, CronExpressionUtil.LoopRule.EveryDay, null);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, expression);
        return success("将于每天的【" + DateUtil.formatDate(time, DateUtil.PATTERN_HH_mm_ss) + "】执行");
    }


    /**
     * 添加设备每天重复定时任务,time 只接受 HH:mm:ss 格式
     *
     * @param sensorNo
     * @param time
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备每天重复定时任务,time 只接受 HH:mm:ss 格式")
    @PostMapping("/addEveryDayByTime/{time}")
    public Response<String> addEveryDayByTime(String sensorNo, @PathVariable String time,Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        String expression = CronExpressionUtil.getExpression(time, CronExpressionUtil.LoopRule.EveryDay, null);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, expression);
        return success("将于每天的【" + time + "】执行");
    }

    /**
     * 添加设备按周一到周五重复定时任务
     *
     * @param sensorNo
     * @param hour
     * @param min
     * @param sec
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备按周一到周五重复定时任务")
    @PostMapping("/addWeek1To5ByTime/{hour}/{min}/{sec}")
    public Response<String> addWeek1To5ByTime(String sensorNo, @PathVariable int hour, @PathVariable int min, @PathVariable int sec,Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        Date time = DateUtil.getTime(hour, min, sec);
        String expression = CronExpressionUtil.getExpression(time, CronExpressionUtil.LoopRule.Week1To5, null);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, expression);
        return success("将于周一到周五的每天【" + DateUtil.formatDate(time, DateUtil.PATTERN_HH_mm_ss) + "】执行");
    }

    /**
     * 添加设备按周一到周五重复定时任务,time 只接受 HH:mm:ss 格式
     *
     * @param sensorNo
     * @param time
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备按周一到周五重复定时任务,time 只接受 HH:mm:ss 格式")
    @PostMapping("/addWeek1To5ByTime/{time}")
    public Response<String> addWeek1To5ByTime(String sensorNo, @PathVariable String time,Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        String expression = CronExpressionUtil.getExpression(time, CronExpressionUtil.LoopRule.Week1To5, null);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, expression);
        return success("将于周一到周五的每天【" + time + "】执行");
    }

    /**
     * 添加设备按周六周日重复定时任务
     *
     * @param sensorNo
     * @param hour
     * @param min
     * @param sec
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备按周六周日重复定时任务")
    @PostMapping("/addWeek67ByTime/{hour}/{min}/{sec}")
    public Response<String> addWeek67ByTime(String sensorNo, @PathVariable int hour, @PathVariable int min, @PathVariable int sec,
                                           Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        Date time = DateUtil.getTime(hour, min, sec);
        String expression = CronExpressionUtil.getExpression(time, CronExpressionUtil.LoopRule.Week67, null);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, expression);
        return success("将于周六周日的每天【" + DateUtil.formatDate(time, DateUtil.PATTERN_HH_mm_ss) + "】执行");
    }

    /**
     * 添加设备按周六周日重复定时任务,time 只接受 HH:mm:ss 格式
     *
     * @param sensorNo
     * @param time
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备按周六周日重复定时任务,time 只接受 HH:mm:ss 格式")
    @PostMapping("/addWeek67ByTime/{time}")
    public Response<String> addWeek67ByTime(String sensorNo, @PathVariable String time,
                                           Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        String expression = CronExpressionUtil.getExpression(time, CronExpressionUtil.LoopRule.Week67, null);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, expression);
        return success("将于周六周日的每天【" + time + "】执行");
    }

    /**
     * 添加设备按星期自定义重复定时任务
     *
     * @param sensorNo
     * @param hour
     * @param min
     * @param sec
     * @param weeks
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备按星期自定义重复定时任务", notes = "星期传值需要特别注意，格式为类似 1,3,5，即周日周二周四，实际星期要在数字的基础上减1,即一周的第一天为周日。")
    @PostMapping("/addWeekByTime/{hour}/{min}/{sec}/{weeks}")
    public Response<String> addWeekByTime(String sensorNo, @PathVariable int hour, @PathVariable int min, @PathVariable int sec,
                                          @PathVariable String weeks,  Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        Date time = DateUtil.getTime(hour, min, sec);
        String expression = CronExpressionUtil.getExpression(time, CronExpressionUtil.LoopRule.Week, weeks);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, expression);
        return success("将于指定星期的每天【" + DateUtil.formatDate(time, DateUtil.PATTERN_HH_mm_ss) + "】执行");
    }

    /**
     * 添加设备按星期自定义重复定时任务
     *
     * @param sensorNo
     * @param time
     * @param weeks
     * @param mqttMessage
     * @param remark
     * @return
     */
    @ApiOperation(value = "添加设备按星期自定义重复定时任务。time 只接受 HH:mm:ss 格式。", notes = "time 只接受 HH:mm:ss 格式。星期传值需要特别注意，格式为类似 1,3,5，即周日周二周四，实际星期要在数字的基础上减1,即一周的第一天为周日。")
    @PostMapping("/addWeekByTime/{time}/{weeks}")
    public Response<String> addWeekByTime(String sensorNo, @PathVariable String time,
                                          @PathVariable String weeks, Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        String expression = CronExpressionUtil.getExpression(time, CronExpressionUtil.LoopRule.Week, weeks);
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, expression);
        return success("将于指定星期的每天【" + time + "】执行");
    }


    /**
     * 自己写cron表达式下发定时任务
     * @param sensorNo
     * @param cronExpression
     * @param time0
     * @param remark
     * @param isDeleteOneTime
     * @return
     */
    @ApiOperation(value = "自己写cron表达式下发定时任务")
    @PostMapping("/addByCronExpression")
    public Response<String> addByCronExpression(String sensorNo, String cronExpression,Date time1, Date time2, String remark, Boolean isDeleteOneTime) {
        addSchedule(sensorNo, time1, time2, remark, isDeleteOneTime, cronExpression);
        return success("将按表达式【"+cronExpression+"】执行");
    }

    /**
     * 获取设备定时任务列表
     *
     * @param sensorNo
     * @return
     */
    @ApiOperation(value = "获取设备定时任务列表", notes = "如果一个设备只录入一个定时任务，那么此返回的列表中记录只有一条")
    @GetMapping("/get/list")
    public Response<List<SchedulerTaskToSendTCPMessage>> getList(String sensorNo) {
        List<SchedulerTaskToSendTCPMessage> schedulerTaskToSendTCPMessageList = schedulerTaskToSendTCPMessageDao.findBySensorNo(sensorNo);
        return success(schedulerTaskToSendTCPMessageList);
    }

    /**
     * 删除且停止一个定时任务
     *
     * @param schedulerTaskToSendTCPMessageId
     * @return
     */
    @ApiOperation(value = "删除且停止一个定时任务", notes = "schedulerTaskToSendTCPMessageId为SchedulerTaskToSendTCPMessage的主键")
    @GetMapping("/delete/{schedulerTaskToSendTCPMessageId}")
    public Response<Void> delete(@PathVariable Long schedulerTaskMqttMessageId) {
        SchedulerTaskToSendTCPMessage schedulerTaskToSendTCPMessage = schedulerTaskToSendTCPMessageDao.findOne(schedulerTaskMqttMessageId);
        HlAssert.notNull(schedulerTaskToSendTCPMessage, "无效的参数");
        String sensorNo = schedulerTaskToSendTCPMessage.getSensorNo();
        schedulerTaskSensorDataService.delete(schedulerTaskToSendTCPMessage);
        return success();
    }

}
